#include <boost\bind.hpp>
#include "registry.h"

namespace cs
{
	registry::registry() : last_addres_(0), logger("cs_registry") {}

	address registry::add_session(session_ptr new_session)
	{
		sessions_map.insert(sessions_map_t::value_type(++last_addres_, new_session));
		logger.log_info("Added new session to registry with id [%d].", last_addres_);
		return last_addres_;
 	}

	void registry::remove_session(session_ptr session)
	{
		sessions_map_t::right_const_iterator it = sessions_map.right.find(session);
		
		if (it != sessions_map.right.end()) {
			logger.log_info("Removed session with id [%d]", it->second);
			services_map.left.erase(it->second);
			subscribers_map.erase(it->second);
			sessions_map.right.erase(session);
		}
	}

	address registry::find_address(registry::session_ptr session)
	{
		sessions_map_t::right_const_iterator it = sessions_map.right.find(session);
		if ( it != sessions_map.right.end()) {
			return it->second;
		}

		return address();
	}

	registry::session_ptr registry::find_session(const address& addr)
	{
		sessions_map_t::left_const_iterator it = sessions_map.left.find(addr);
		if (it != sessions_map.left.end()) {
			return it->second;
		}
		return session_ptr();
	}

	bool registry::register_service(session_ptr session, const std::string& service_name)
	{
		sessions_map_t::right_const_iterator it = sessions_map.right.find(session);

		if ((it != sessions_map.right.end()) && 
			(services_map.right.find(service_name) == services_map.right.end())) {
				logger.log_info("Registered new service [%s] with session id [%d]", service_name.c_str(), it->second);
				services_map.insert(services_map_t::value_type(it->second, service_name));
				return true;
		}

		return false;
	}

	address registry::get_service_address(const std::string& service_name)
	{
		services_map_t::right_const_iterator it = services_map.right.find(service_name);
		if (it != services_map.right.end()) {
			return it->second;
		}

		return address();
	}

	address registry::subscribe_sevice(session_ptr session, const std::string& service_name)
	{
		sessions_map_t::right_const_iterator it = sessions_map.right.find(session);

		if (it != sessions_map.right.end() && 
			!is_in_subscribers_map(it->second, service_name)) {
			subscribers_map.insert(std::make_pair(it->second, service_name));
			logger.log_info("Subscribed session id [%d] for [%s]", it->second, service_name.c_str());
			services_map_t::right_const_iterator it2 = services_map.right.find(service_name);
			return (it2 != services_map.right.end()) ? it2->second : address();
		}
		return address();
	}

	void registry::clear_address_generator()
	{
#ifdef _DEBUG
		last_addres_ = 0;
#endif
	}

	bool registry::is_in_subscribers_map(const address& addr, const std::string& str)
	{
		subscribers_map_t::const_iterator it = subscribers_map.find(addr);
		if (it != subscribers_map.end() && it->second == str) {
			return true;
		}
		return false;
	}

	registry::subscriber_list_t registry::get_subscribers(const std::string& service_name)
	{
		subscriber_list_t list;
		for(subscribers_map_t::const_iterator it = subscribers_map.begin(); it != subscribers_map.end(); it++) {
			if (it->second == service_name) {
				list.push_back(sessions_map.left.at(it->first));
			}
		}
		return list;
	}
}